$(document).ready(function() {

	//Set up the presentation layer
	presentationLayer = new PresentationLayer();

	//Initialise the presentation layer for the application
	presentationLayer.initialise();

});

function PresentationLayer() {
	this.businessLayer = new BusinessLayer();
};

PresentationLayer.prototype.initialise = function() {

	jQuery("#adviserwebapp").hide();
	jQuery(".alert").html("").hide();
	jQuery('#myModal').modal('show');

	this.setUpLogin();

};

PresentationLayer.prototype.setUpLogin = function() {
	var self = this;

	var loginForm = jQuery('#loginForm');

	jQuery('.logIn').click(function() {
		if (loginForm.valid()) {
			self.processLogIn();
		}
	});

	var loginValidator = loginForm.validate({
		rules : {
			pNo : {
				required : true
			},
			pWord : {
				required : true
			}
		},
		errorPlacement : function(error, element) {
			element.next('.vError').remove();
			element.after('<div class="vError"><span class="arrow"></span>' + error.html() + '</div>');
		},
		success : function(error, element) {
			jQuery(element).next().remove();
		}
	});
};

PresentationLayer.prototype.setUpGeneralCallBacks = function() {
	var self = this;

	var form = jQuery('#paymentForm');
	var idleTimer;
	jQuery.support.cors = true;
	jQuery("body").on('click keyup', function() {
		clearTimeout(idleTimer);
		idleTimer = setTimeout(function() {
			var modalVisible = jQuery('#myModal').is(':visible');
			if (!modalVisible) {
				self.resetForm();
				jQuery('#myModal').modal('show');
			}
		}, 300000);
	});
	jQuery(".sendPayment").click(function() {
		if (form.valid()) {
			self.processPayment();
		}
	});
	jQuery('.resetForm').click(function() {
		self.resetForm();
	});

	jQuery.validator.addMethod("mobilePhone", function(value, element) {
		return this.optional(element) || (value.substring(0, 2) == "07");
	}, "UK mobile numbers must start 07");
	jQuery.validator.addMethod("poundsPence", function(value, element) {
		return this.optional(element) || /^\d{0,10}(\.\d{0,2})?$/i.test(value);
	}, "Currency has a maximum of two decimal places");
	var payLimit = this.businessLayer.getUserDetails().getLimit();
	var validator = form.validate({

		rules : {
			mobileNo : {
				required : true,
				digits : true,
				mobilePhone : true
			},
			amount : {
				required : true,
				number : true,
				min : 0,
				poundsPence : true,
				max : payLimit
			}
		},
		messages : {
			mobileNo : {
				required : "Please enter a mobile phone number",
				digits : "Numbers only, no text"
			},
			amount : {
				required : "Please enter a payment amount",
				number : "Numbers only, no text",
				min : "Please enter a payment amount greater than 0",
				max : "You are not authorised for payments over &pound;" + payLimit
			}
		},
		errorPlacement : function(error, element) {
			element.next('.vError').remove();
			element.after('<div class="vError"><span class="arrow"></span>' + error.html() + '</div>');
		},
		success : function(error, element) {
			jQuery(element).next().remove();
		}
	});
};

PresentationLayer.prototype.resetForm = function() {
	jQuery("#pNo").val("");
	jQuery("#pWord").val("");
	jQuery("#mobileNo").val("");
	jQuery("#amount").val("");
	jQuery("#desc").val("");
	jQuery(".alert").html("").hide();
};

PresentationLayer.prototype.processPayment = function() {
	var userInputs = this.getInputs();

	var response = this.businessLayer.callService(userInputs);

	this.processResponse(response);
};

PresentationLayer.prototype.processLogIn = function() {

	var pNo = jQuery("#pNo").val();
	var response = this.businessLayer.processLogIn(pNo.toLowerCase());
	if (response == "SUCCESS") {
		this.setUpGeneralCallBacks();
		var userName = this.businessLayer.getUserDetails().getName();
		jQuery("#userName").html(userName);
		jQuery('#myModal').modal('hide');
		jQuery("#adviserwebapp").show();
		jQuery(".alert").hide();
	} else {
		jQuery(".alert-error").html("Invalid User Credentials").show();
	}
};

PresentationLayer.prototype.processResponse = function(response) {
	//alert(response.getStatus() + ' - ' + response.getDesc());
	var status = response.getStatus();
	var desc = response.getDesc();
	var msg = "";

	if (status.toUpperCase() == 'SUCCESS') {
		msg = '<b>' + status.toUpperCase() + '</b>' + ' - ' + desc + ' - request queued for payment. Click Reset to process another payment.';
		jQuery(".alert-success").html(msg).show();
		//this.resetForm();
	} else {
		msg = '<b>' + status.toUpperCase() + '</b>' + ' - ' + desc + ' - contact Imagine Support. Click Reset to process another payment.';
		jQuery(".alert-error").html(msg).show();
	}
};

PresentationLayer.prototype.getInputs = function() {
	var mob = jQuery.encoder.encodeForHTML(jQuery("#mobileNo").val());
	var amt = jQuery.encoder.encodeForHTML(jQuery("#amount").val());
	var desc = jQuery.encoder.encodeForHTML(jQuery("#desc").val());

	var userInputs = new UserInput(mob, amt, desc);

	return userInputs;

};

function BusinessLayer() {
	this.dataAccessLayer = new DataAccessLayer();
	this.response = "";
};

BusinessLayer.prototype.callService = function(userInputs) {
	var response = this.dataAccessLayer.callService(userInputs);
	return response;
};

BusinessLayer.prototype.processLogIn = function(pNo) {
	var response = this.dataAccessLayer.processLogIn(pNo);
	return response;
};

BusinessLayer.prototype.getUserDetails = function(pNo) {
	var response = this.dataAccessLayer.getUserDetails();
	return response;
};

function DataAccessLayer() {
	this.responseStatus = "";
	this.responseDesc = "";
	this.userDetails = null;
};
DataAccessLayer.prototype.loadUserDTO = function() {
	//Load the data transfer object
	var userDTO = null;
	jQuery.ajax({
		'async' : false,
		'url' : "./data/data.json",
		'dataType' : "json",
		'success' : function(json) {
			userDTO = json;
		}
	});

	return userDTO;
};

DataAccessLayer.prototype.processLogIn = function(pNo) {

	var name, limit, status = 'FAILURE';

	//Load the data transfer objects
	var userDTO = this.loadUserDTO();

	if (userDTO[pNo] === undefined) {
		name = 'error';
		limit = -1;
	} else {
		name = userDTO[pNo].name;
		limit = userDTO[pNo].limit;
		status = 'SUCCESS';
	}
	
	this.userDetails = new UserDetails(pNo,name,limit);

	return status;

};

DataAccessLayer.prototype.getUserDetails = function(){
	return this.userDetails;
};


DataAccessLayer.prototype.callService = function(userInputs) {
	var self = this;
	var webServiceURL = 'http://lgrdcpdd501:8080/mpayments/services/mpaymentsSOAP';
	var soapMessage = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mpay="http://www.example.org/mpayments/">';
	soapMessage += '<soapenv:Header/><soapenv:Body><mpay:submitPayment>';
	soapMessage += '<amount>' + userInputs.getAmt() + '</amount>';
	soapMessage += '<mobileNo>' + userInputs.getMob() + '</mobileNo>';
	soapMessage += '<description>' + userInputs.getDesc() + '</description>';
	soapMessage += '</mpay:submitPayment></soapenv:Body></soapenv:Envelope>';

	jQuery.ajax({
		async : false,
		url : webServiceURL,
		type : "POST",
		dataType : "xml",
		data : soapMessage,
		processData : false,
		contentType : "text/xml; charset=\"utf-8\"",
		headers : {
			SOAPAction : webServiceURL
		},
		success : function(data, status) {
			self.responseStatus = jQuery.encoder.encodeForHTML(status);
			self.responseDesc = jQuery.encoder.encodeForHTML($(data).find('ack').text());
		},
		error : function(request, status, error) {
			self.responseStatus = jQuery.encoder.encodeForHTML(status);
			self.responseDesc = jQuery.encoder.encodeForHTML(error);
		}
	});

	var serviceResponse = new ServiceResponse(this.responseStatus, this.responseDesc);

	return serviceResponse;

};

function UserInput(mob, amt, desc) {
	this.mob = mob;
	this.amt = amt;
	this.desc = desc;
};

UserInput.prototype.getMob = function() {
	return this.mob;
};

UserInput.prototype.getAmt = function() {
	return this.amt;
};

UserInput.prototype.getDesc = function() {
	return this.desc;
};

function ServiceResponse(status, desc) {
	this.status = status;
	this.desc = desc;
};

ServiceResponse.prototype.getStatus = function() {
	return this.status;
};

ServiceResponse.prototype.getDesc = function() {
	return this.desc;
};

function UserDetails(pNo, name, limit) {
	this.pNo = pNo;
	this.name = name;
	this.limit = limit;
};

UserDetails.prototype.getPNo = function() {
	return this.namepNo;
};

UserDetails.prototype.getName = function() {
	return this.name;
};

UserDetails.prototype.getLimit = function() {
	return this.limit;
};
